package edu.ccut.saturn.studio.logic.model;

import java.util.List;

import org.eclipse.draw2d.Graphics;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;

import edu.ccut.saturn.studio.dialog.SaturnDecisionConnectionDialog;
import edu.ccut.saturn.studio.dialog.SaturnRouterConnectionDialog;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnComponentNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnDecisionNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnEndIterationNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnEndNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnInformationNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnLogicNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnStartIterationNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnStartNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnSwichNode;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnSwichVO;
import edu.ccut.saturn.studio.logic.model.saturn.SaturnWorkflowNodeInLogic;

public class Connection extends BasicShape {

	private static final long serialVersionUID = 1129718762625130932L;

	public static final Integer SOLID_CONNECTION = Graphics.LINE_SOLID;

	public static final Integer DASHED_CONNECTION = Graphics.LINE_DASH;

	public static final String LINESTYLE_PROP = "LineStyle";

	private boolean isConnected;

	public static final String LINE_NAME_PROPERTY = "line_name_property";

	private int lineStyle = Graphics.LINE_SOLID;

	public static final Integer EXCEPTION_CONNECTION = Graphics.LINE_CUSTOM;

	private Shape source;

	private Shape target;

	private String lineName = "";

	public Connection(Shape source, Shape target, int lineStyle) {
		this.lineStyle = lineStyle;
		reconnect(source, target);
	}

	public boolean isConnected() {
		return this.isConnected;
	}

	public void setConnected(boolean isConnected) {
		this.isConnected = isConnected;
	}

	public void disconnect() {
		if (this.isConnected) {
			this.source.removeConnection(this);
			this.target.removeConnection(this);

			if (this.source instanceof SaturnSwichNode) {
				List<SaturnSwichVO> list = ((SaturnSwichNode) source)
						.getSaturnSwichConnections();
				for (int i = 0; i < list.size(); i++) {
					if (this.target.getId().equals(list.get(i).getConnection())) {
						list.remove(i);
					}
				}
			}

			this.isConnected = false;
			if (this.lineStyle == Connection.EXCEPTION_CONNECTION
					&& (this.source instanceof SaturnLogicNode)) {
				((SaturnLogicNode) this.source).setException("");

			} else if (this.lineStyle == Connection.EXCEPTION_CONNECTION
					&& (this.source instanceof SaturnComponentNode)) {
				((SaturnComponentNode) this.source).setException("");

			} else if (this.lineStyle == Connection.EXCEPTION_CONNECTION
					&& (this.source instanceof SaturnWorkflowNodeInLogic)) {
				((SaturnComponentNode) this.source).setException("");

			} else if (this.lineStyle == Connection.DASHED_CONNECTION
					&& (this.source instanceof SaturnDecisionNode)) {
				((SaturnDecisionNode) this.source).setFalseId("");

			} else if (this.lineStyle == Connection.SOLID_CONNECTION
					&& (this.source instanceof SaturnDecisionNode)) {
				((SaturnDecisionNode) this.source).setThenid("");

			} else if (this.lineStyle == Connection.SOLID_CONNECTION) {
				this.source.setNextId("");
			}
		}
	}

	public int getLineStyle() {
		return lineStyle;
	}

	public Shape getSource() {
		return source;
	}

	public Shape getTarget() {
		return target;
	}

	public String getLineName() {
		return lineName;
	}

	public void setLineName(String lineName) {
		this.lineName = lineName;
		firePropertyChange(LINE_NAME_PROPERTY, null, lineName);
	}

	public void reconnect() {
		if (!isConnected) {

			/**
			 * 禁止自己连接自己
			 */
			if (source.equals(target)) {
				throw new IllegalArgumentException();
			}
			/**
			 * 只有选择可以使用分支连线
			 */
			if (lineStyle == Graphics.LINE_DASH
					&& !(this.source instanceof SaturnDecisionNode)) {
				throw new IllegalArgumentException();
			}
			/**
			 * 逻辑、组件和工作流可以使用异常连线
			 */

			if (lineStyle == Graphics.LINE_CUSTOM
					&& (!((this.source instanceof SaturnLogicNode)
							|| (this.source instanceof SaturnComponentNode) || (this.source instanceof SaturnWorkflowNodeInLogic)))) {
				throw new IllegalArgumentException();
			}

			/**
			 * 开始节点不能被连接,结束节点不能连接出去
			 */
			if ((source instanceof SaturnEndNode)
					|| (target instanceof SaturnStartNode)) {
				return;
			}
			/**
			 * 循环开如不能直接连接循环结束
			 */
			if ((source instanceof SaturnStartIterationNode)
					&& (target instanceof SaturnEndIterationNode)) {
				return;
			}
			/**
			 * 描述信息不能被连接和连接别人
			 */
			if ((source instanceof SaturnInformationNode)
					|| (target instanceof SaturnInformationNode)) {
				return;
			}

			/**
			 * 每一种连线只能使用一次
			 */
			if (this.lineStyle == Graphics.LINE_SOLID) {
				if (source.getSourceConnections().size() != 0) {
					for (int i = 0; i < this.source.getSourceConnections()
							.size(); i++) {
						if (source.getSourceConnections().get(i).getLineStyle() == 1) {
							if (!(source instanceof SaturnSwichNode)) {
								return;
							}
						}
					}
				}
			}

			if (this.lineStyle == Graphics.LINE_DASH) {
				if (source.getSourceConnections().size() != 0) {
					for (int i = 0; i < this.source.getSourceConnections()
							.size(); i++) {
						if (source.getSourceConnections().get(i).getLineStyle() == 2) {
							return;
						}
					}
				}
			}

			if (this.lineStyle == Graphics.LINE_CUSTOM
					&& (((this.source instanceof SaturnLogicNode) || (this.source instanceof SaturnComponentNode)))) {
				if (source.getSourceConnections().size() != 0) {
					for (int i = 0; i < this.source.getSourceConnections()
							.size(); i++) {
						if (source.getSourceConnections().get(i).getLineStyle() == 6) {
							return;
						}
					}
				}
			}

			/**
			 * 禁止反向连接
			 */

			if (target.getSourceConnections().size() != 0) {
				for (int i = 0; i < target.getSourceConnections().size(); i++) {
					if (target.getSourceConnections().get(i).getTarget()
							.equals(source)) {
						return;
					}
				}
			}

			if ((this.source instanceof SaturnDecisionNode)
					&& (this.lineStyle == Connection.DASHED_CONNECTION)) {
				((SaturnDecisionNode) this.source).setFalseId(this.target
						.getId());
			}
			if ((this.source instanceof SaturnDecisionNode)
					&& (this.lineStyle == Connection.SOLID_CONNECTION)) {
				((SaturnDecisionNode) this.source)
						.setThenid(this.target.getId());
			}
			if (this.source instanceof SaturnDecisionNode) {
				this.source.setNextId("");
			}
			if ((this.source instanceof SaturnLogicNode)
					&& this.lineStyle == Connection.EXCEPTION_CONNECTION) {
				((SaturnLogicNode) this.source)
						.setException(this.target.getId());
			}
			if ((this.source instanceof SaturnComponentNode)
					&& this.lineStyle == Connection.EXCEPTION_CONNECTION) {
				((SaturnComponentNode) this.source).setException(this.target
						.getId());
			}
			if ((this.source instanceof SaturnWorkflowNodeInLogic)
					&& this.lineStyle == Connection.EXCEPTION_CONNECTION) {
				((SaturnWorkflowNodeInLogic) this.source)
						.setException(this.target.getId());
			}
			if ((this.source instanceof SaturnDecisionNode)
					&& this.lineStyle == Connection.SOLID_CONNECTION) {
				((SaturnDecisionNode) this.source).setNextId("");
			} else if (Connection.SOLID_CONNECTION == this.lineStyle) {
				this.source.setNextId(this.target.getId());
			}

			source.addConnection(this);
			target.addConnection(this);

			isConnected = true;
		}
	}

	public void reconnect(Shape newSource, Shape newTarget) {
		if (newSource == null || newTarget == null || newSource == newTarget) {
			throw new IllegalArgumentException();
		}
		if (newSource instanceof SaturnSwichNode) {
			SaturnSwichVO saturn = new SaturnSwichVO();
			saturn.setConnection(newTarget.getId());
			List<SaturnSwichVO> list = ((SaturnSwichNode) newSource)
					.getSaturnSwichConnections();
			if (isAdd(list, saturn.getConnection())) {
				list.add(saturn);
			}
		}
		disconnect();
		this.source = newSource;
		this.target = newTarget;
		reconnect();
	}

	private boolean isAdd(List<SaturnSwichVO> list, String id) {
		for (SaturnSwichVO vo : list) {
			if (vo.getConnection().equals(id)) {
				return false;
			}
		}
		return true;
	}

	public void setLineStyle(int lineStyle) {
		if (lineStyle != Graphics.LINE_DASH && lineStyle != Graphics.LINE_SOLID) {
			throw new IllegalArgumentException();
		}
		this.lineStyle = lineStyle;
		firePropertyChange(LINESTYLE_PROP, null, new Integer(this.lineStyle));
	}

	public Color getColor() {
		if (this.lineStyle == SOLID_CONNECTION) {
			return new Color(null, 0, 0, 0);
		} else if (this.lineStyle == DASHED_CONNECTION) {
			return new Color(null, 31, 112, 42);
		} else if (this.lineStyle == EXCEPTION_CONNECTION) {
			return new Color(null, 255, 0, 0);
		}

		return new Color(null, 0, 0, 0);
	}

	public Dialog getDialog() {
		if (this.source instanceof SaturnDecisionNode) {
			return new SaturnDecisionConnectionDialog(Display.getDefault()
					.getShells()[0], this);
		} else {
			return new SaturnRouterConnectionDialog(Display.getDefault()
					.getShells()[0], this);
		}
	}
}